use std::sync::Arc;
use log::{info, warn, error, debug, trace};
use axum::{
    Router,
    routing::{get, post},
    extract::{Path, State, DefaultBodyLimit, Json},
    http::{HeaderMap, StatusCode},
    response::Response,
    body::Body,
};
use bytes::Bytes;
use rocksdb::IteratorMode;
use crate::db::{DatabaseManager, Db};
use crate::error::ApiError;

// 路由直接使用 DatabaseManager 的 Arc 作为状态

fn db_open_error(name: &str, e: impl std::fmt::Display) -> ApiError {
    error!("获取数据库失败 - 数据库: {}, 错误: {}", name, e);
    ApiError::Internal(format!("Database error: {}", e))
}

// 统一的数据库打开辅助函数，便于用 `?` 传播错误
async fn open_db_or_err(db_manager: &Arc<DatabaseManager>, name: &str) -> Result<Db, ApiError> {
    db_manager
        .get_db(name)
        .map_err(|e| db_open_error(name, e))
}

pub fn router() -> Router<Arc<DatabaseManager>> {
    Router::new()
        .route(
            "/api/:name/:key",
            get(get_value).put(set_binary_value).delete(delete_key).head(head_key),
        )
        .route(
            "/api/:name/_mget",
            post(batch_get),
        )
        .route(
            "/api/:name",
            get(list_keys),
        )
        .layer(DefaultBodyLimit::max(10 * 1024 * 1024))
}

// 获取值
async fn get_value(
    Path((name, key)): Path<(String, String)>,
    State(db_manager): State<Arc<DatabaseManager>>,
    headers: HeaderMap,
) -> Result<Response, ApiError> {
    debug!("收到获取值请求，数据库: {}, 键: {}", name, key);
    let db = open_db_or_err(&db_manager, &name).await?;
    match db.get(key.as_bytes()) {
        Ok(Some(value)) => {
            // 检查请求头是否要求返回二进制数据
            let content_type = headers.get("accept")
                .and_then(|h| h.to_str().ok())
                .unwrap_or("");

            if content_type == "application/octet-stream" {
                // 直接返回二进制数据
                debug!("成功获取二进制数据 - 键: {}, 数据大小: {} 字节", key, value.len());
                return Ok(Response::builder()
                    .status(StatusCode::OK)
                    .header("Content-Type", "application/octet-stream")
                    .body(Body::from(value))
                    .unwrap());
            } else {
                // 返回字符串数据
                let value_str = String::from_utf8_lossy(&value).to_string();
                debug!("成功获取键值对 - 键: {}, 值: {}", key, value_str.len());
                return Ok(Response::builder()
                    .status(StatusCode::OK)
                    .header("Content-Type", "text/plain; charset=utf-8")
                    .body(Body::from(value_str))
                    .unwrap());
            }
        }
        Ok(None) => {
            warn!("键未找到: {}", key);
            // 直接返回200状态码，不返回JSON数据
            Err(ApiError::NotFound)
        }
        Err(e) => {
            error!("数据库错误，键: {}, 错误: {}", key, e);
            Err(ApiError::Internal(format!("Database error: {}", e)))
        }
    }
}


// 删除键
async fn delete_key(
    Path((name, key)): Path<(String, String)>,
    State(db_manager): State<Arc<DatabaseManager>>,
) -> Result<Response, ApiError> {
    debug!("收到删除键请求 - 数据库: {}, 键: {}", name, key);
    let db = open_db_or_err(&db_manager, &name).await?;
    match db.delete(key.as_bytes()) {
        Ok(_) => {
            info!("成功删除键: {}", key);
            // 直接返回200状态码，不返回JSON数据
            Ok(Response::builder().status(StatusCode::OK).body(Body::empty()).unwrap())
        }
        Err(e) => {
            error!("删除键失败 - 键: {}, 错误: {}", key, e);
            Err(ApiError::Internal(format!("Database error: {}", e)))
        }
    }
}

// HEAD 判断键是否存在，存在则返回值大小（使用 pinned slice），不返回Body
async fn head_key(
    Path((name, key)): Path<(String, String)>,
    State(db_manager): State<Arc<DatabaseManager>>,
) -> Result<Response, ApiError> {
    debug!("收到HEAD请求 - 数据库: {}, 键: {}", name, key);
    let db = open_db_or_err(&db_manager, &name).await?;
    match db.get_pinned(key.as_bytes()) {
        Ok(Some(slice)) => {
            let len = slice.len();
            debug!("键存在 - 键: {}, 值大小: {} 字节", key, len);
            Ok(Response::builder()
                .status(StatusCode::OK)
                .header("X-Value-Length", len.to_string())
                .body(Body::empty())
                .unwrap())
        }
        Ok(None) => {
            warn!("键未找到: {}", key);
            Ok(Response::builder()
                .status(StatusCode::NOT_FOUND)
                .body(Body::empty())
                .unwrap())
        }
        Err(e) => {
            error!("数据库错误，键: {}, 错误: {}", key, e);
            Err(ApiError::Internal(format!("Database error: {}", e)))
        }
    }
}

// 列出所有键
async fn list_keys(
    Path(name): Path<String>,
    State(db_manager): State<Arc<DatabaseManager>>,
) -> Result<Response, ApiError> {
    debug!("收到列出所有键的请求 - 数据库: {}", name);
    let db = open_db_or_err(&db_manager, &name).await?;
    // Db 是 Arc<DB>，无需加锁
    let mut keys = Vec::new();

    let iter = db.iterator(IteratorMode::Start);
    for item in iter {
        match item {
            Ok((key, _)) => {
                if let Ok(key_str) = String::from_utf8(key.to_vec()) {
                    keys.push(key_str);
                }
            }
            Err(e) => {
                error!("遍历数据库时发生错误: {}", e);
                return Err(ApiError::Internal(format!("Iterator error: {}", e)));
            }
        }
    }

    debug!("成功列出所有键，共 {} 个键", keys.len());
    trace!("键列表: {:?}", keys);
    Ok(Response::builder()
        .status(StatusCode::OK)
        .header("Content-Type", "text/plain; charset=utf-8")
        .body(Body::from(keys.join("\n")))
        .unwrap())
}

// 设置二进制值
async fn set_binary_value(
    Path((name, key)): Path<(String, String)>,
    State(db_manager): State<Arc<DatabaseManager>>,
    headers: HeaderMap,
    body: Bytes,
) -> Result<Response, ApiError> {
    let content_type = headers
        .get("content-type")
        .and_then(|h| h.to_str().ok())
        .unwrap_or("application/octet-stream");

    let db = open_db_or_err(&db_manager, &name).await?;

    trace!("准备将二进制数据写入数据库 - 键: {}, 数据大小: {} 字节, Content-Type: {}", key, body.len(), content_type);
    match db.put(key.as_bytes(), &body) {
        Ok(_) => {
            debug!("成功保存二进制数据到数据库 - 键: {}, 数据大小: {} 字节", key, body.len());
            // 直接返回200状态码，不返回JSON数据
            Ok(Response::builder().status(StatusCode::OK).body(Body::empty()).unwrap())
        }
        Err(e) => {
            error!("保存二进制数据到数据库失败 - 键: {}, 数据大小: {} 字节, 错误: {}", key, body.len(), e);
            Err(ApiError::Internal(format!("Database error: {}", e)))
        }
    }
}

// 批量获取：POST /api/:name/_mget  body: {"keys": ["k1", "k2"]}
async fn batch_get(
    Path(name): Path<String>,
    State(db_manager): State<Arc<DatabaseManager>>,
    Json(keys): Json<Vec<String>>,
) -> Result<Response, ApiError> {
    debug!("收到批量获取请求 - 数据库: {}, 键数量: {}", name, keys.len());
    let db = open_db_or_err(&db_manager, &name).await?;

    let mut map = std::collections::HashMap::new();
    for key in keys.iter() {
        match db.get(key.as_bytes()) {
            Ok(Some(value)) => {
                let value_str = String::from_utf8_lossy(&value).to_string();
                map.insert(key.clone(), value_str);
            }
            Ok(None) => {
                // 不存在的键跳过，不在响应中体现
                trace!("批量获取 - 键未找到: {}", key);
            }
            Err(e) => {
                error!("批量获取 - 数据库错误，键: {}, 错误: {}", key, e);
                return Err(ApiError::Internal(format!("Database error: {}", e)));
            }
        }
    }

    let body = serde_json::to_vec(&map).map_err(|e| ApiError::Internal(format!("Serialize error: {}", e)))?;
    Ok(Response::builder()
        .status(StatusCode::OK)
        .header("Content-Type", "application/json")
        .body(Body::from(body))
        .unwrap())
}